package businessLogic;

import java.sql.Connection;
import java.sql.Date;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import Beans.Artigiano;
import Beans.Partner;
import Beans.TipoArtigiano;
import connessioni.MyConnection;
import eccezioni.UtenteNonTrovatoException;


public class GestioneArtigianiMySQL extends GestioneArtigianiEmpty {
	
	private Connection con;
	
	public GestioneArtigianiMySQL() throws SQLException, ClassNotFoundException {
		con = MyConnection.getConnection();
	}
	
	
	/**
	 * il synchronized serve per evitare inserimenti concorrenti
	 * che potrebbero portare problemi tra l'insert e il successivo
	 * getMaxID per memorizzare tel/fax
	 */
	public synchronized void aggiungiArtigiano(Artigiano a) throws SQLException {

		Statement st = con.createStatement();
		
		st.executeUpdate("insert into artigiani(Nome, Cognome, PIva, Email, TipoPartner, TipoArtigiano, Note, " + 
				"Nazione, Regione, Citta, CAP, Provincia, Via, NCivico, PathImg) "
				        + "values('" + a.getNome() + "', '" + a.getCognome() + "', '" + a.getPIva() + "', "
				        + "'" + a.getEmail() + "', " + a.getPartner().getID() + ", " + a.getTipoArtigiano().getId() + ", "
				        + "'" + a.getNote() +  "', '" + a.getNazione() + "', '" + a.getRegione() + "', '" + a.getCitta() + "', "
				        + "'" + a.getCap() +  "', '" + a.getProvincia() + "', '" + a.getVia() + "', '" + a.getNCivico() + "', "
				        + "'" + a.getPathImg() + "')");
		
		//mi prendo l'id e setto i numeri di telefono
		ResultSet max = st.executeQuery("select max(ID) from artigiani");
		max.next();
		a.setId(max.getInt(1));
		max.close();
		
		settaTelFax(a, false);
		
		st.close();
	}
	
	
	/**
	 * prende un artigiano e inserisce/modifica i suoi numeri di telefono e fax
	 * se deleted = true, le entry vengono memorizzate in telefono_artigiano_deleted
	 * @param Artigiano a
	 * @param boolean deleted
	 * @throws SQLException 
	 */
	private void settaTelFax(Artigiano a, boolean deleted) throws SQLException {
		
		String[] tel = a.getTelefono();
		String[] fax = a.getFax();
		
		String tabella = "telefono_artigiano";
		if(deleted)
			tabella = "telefono_artigiano_deleted";
		
		//prima li cancello tutti, se ne esistono, poi inserisco i nuovi
		Statement st = con.createStatement();
		
		st.executeUpdate("delete from telefono_artigiano "
		          + "where IDArtigiano = " + a.getId());
		
		//st.close();
		
		for(int i = 0; i < tel.length; i++) {
			st.executeUpdate("INSERT INTO " + tabella + "(IDArtigiano, TipoPartner, Tipo, Numero) "
			        + "values(" + a.getId() + ", " + a.getPartner().getID() + ", 'Tel', '" + tel[i] + "')");
		}
		
		for(int i = 0; i < fax.length; i++) {
			st.executeUpdate("INSERT INTO " + tabella + "(IDArtigiano, TipoPartner, Tipo, Numero) "
			        + "values(" + a.getId() + ", " + a.getPartner().getID() + ", 'Fax', '" + fax[i] + "')");
		}
		
		st.close();
	}
	
	
	
	public synchronized void eliminaArtigiano(Artigiano a) throws SQLException {
		
		Statement st = con.createStatement();
		int oldID = a.getId();
		
		//salvo tutti i dati dell'artigiano nel Bean
		ResultSet artigiano = st.executeQuery("SELECT * FROM artigiani WHERE ID = " + oldID);
		if(!artigiano.next())
			throw new UtenteNonTrovatoException("Artigiano non presente");
		
		a.setNome(artigiano.getString("Nome"));
		a.setCognome(artigiano.getString("Cognome"));
		a.setPIva(artigiano.getString("PIva"));
		a.setEmail(artigiano.getString("Email"));
		a.setNote(artigiano.getString("Note"));
		a.setNazione(artigiano.getString("Nazione"));
		a.setRegione(artigiano.getString("Regione"));
		a.setCitta(artigiano.getString("Citta"));
		a.setCap(artigiano.getString("CAP"));
		a.setProvincia(artigiano.getString("Provincia"));
		a.setVia(artigiano.getString("Via"));
		a.setNCivico(artigiano.getString("NCivico"));
		a.setPathImg(artigiano.getString("PathImg"));
		
		int idPartner = artigiano.getInt("TipoPartner");
		int idTipoArtigiano = artigiano.getInt("TipoArtigiano");
		
		artigiano.close();
		
		Partner p = new Partner();
		p.setID(idPartner);
		a.setPartner(p);
		TipoArtigiano ta = new TipoArtigiano();
		ta.setId(idTipoArtigiano);
		a.setTipoArtigiano(ta);
		
		//prendo tel e fax
		a.setTelefono(getTelefono(a, false));
		a.setFax(getFax(a, false));
 		
		
		//aggiungo le entry nelle tabelle DELETED
		a.setDataCancellazione(new Date(System.currentTimeMillis()));
		
		st.executeUpdate("insert into artigiani_deleted(Nome, Cognome, PIva, Email, TipoPartner, TipoArtigiano, Note, " + 
				"Nazione, Regione, Citta, CAP, Provincia, Via, NCivico, PathImg, DataCancellazione) "
				        + "values('" + a.getNome() + "', '" + a.getCognome() + "', '" + a.getPIva() + "', "
				        + "'" + a.getEmail() + "', " + a.getPartner().getID() + ", " + a.getTipoArtigiano().getId() + ", "
				        + "'" + a.getNote() +  "', '" + a.getNazione() + "', '" + a.getRegione() + "', '" + a.getCitta() + "', "
				        + "'" + a.getCap() +  "', '" + a.getProvincia() + "', '" + a.getVia() + "', '" + a.getNCivico() + "', "
				        + "'" + a.getPathImg() + "', '" + a.getDataCancellazione() + "')");
		
		ResultSet max = st.executeQuery("select max(ID) from artigiani_deleted");
		max.next();
		a.setId(max.getInt(1)); //l'id da "cancellato"
		max.close();
		
		//tel e fax nella tabella cancellato
		settaTelFax(a, true);
		
		
		//elimino le entry
		//artigiani
		st.executeUpdate("DELETE FROM artigiani "
		          + "WHERE ID = " + oldID);
		
		//numeri tel e fax
		st.executeUpdate("DELETE FROM telefono_artigiano WHERE IDArtigiano = " + oldID);
		
		st.close();

	}
	
	
	private String[] getTelefono(Artigiano a, boolean deleted) throws SQLException {
		
		Statement st = con.createStatement();
		
		String tabella = "telefono_artigiano";
		if(deleted)
			tabella = "telefono_artigiano_deleted";
		
		ResultSet n = st.executeQuery("SELECT COUNT(*) FROM " + tabella + " WHERE Tipo = 'Tel' AND IDArtigiano = " + a.getId());
		n.next();
		String[] toReturn = new String[n.getInt(1)];
		n.close();
		
		ResultSet tel = st.executeQuery("SELECT * FROM " + tabella + " WHERE Tipo = 'Tel' AND IDArtigiano = " + a.getId());
		//se non ce ne sono toReturn ha dimensione 0 e tel.next restituisce subito false
		for(int i = 0; tel.next(); i++)
			toReturn[i] = tel.getString("Numero");
		
		tel.close();
		st.close();
		
		return toReturn;
	}
	
	
	private String[] getFax(Artigiano a, boolean deleted) throws SQLException {
		
		Statement st = con.createStatement();
		
		String tabella = "telefono_artigiano";
		if(deleted)
			tabella = "telefono_artigiano_deleted";
		
		ResultSet n = st.executeQuery("SELECT COUNT(*) FROM " + tabella + " WHERE Tipo = 'Fax' AND IDArtigiano = " + a.getId());
		n.next();
		String[] toReturn = new String[n.getInt(1)];
		n.close();
		
		ResultSet tel = st.executeQuery("SELECT * FROM " + tabella + " WHERE Tipo = 'Fax' AND IDArtigiano = " + a.getId());
		//se non ce ne sono toReturn ha dimensione 0 e tel.next restituisce subito false
		for(int i = 0; tel.next(); i++)
			toReturn[i] = tel.getString("Numero");
		
		tel.close();
		st.close();
		
		return toReturn;
	}
	
	
	/**
	 * insieme a getDeleted, richiamano la procedura getArtigianoCommon
	 * in caso di modifiche, non serve aggiornare entrambi i metodi
	 */
	public Artigiano getArtigiano(int id) throws SQLException {
		
		return getArtigianoCommon(id, false);
		
	}
	
	
	public Artigiano getArtigianoDeleted(int id) throws SQLException {

		return getArtigianoCommon(id, true);
		
	}
	
	
	
	private Artigiano getArtigianoCommon(int id, boolean deleted) throws SQLException {
		
		String tabella = "artigiani";
		if(deleted)
			tabella = "artigiani_deleted";
		
		Statement st = con.createStatement();
		
		ResultSet rs = st.executeQuery("SELECT * FROM " + tabella + " WHERE ID = " + id);
		if(!rs.next())
			throw new UtenteNonTrovatoException("Artigiano non presente");
		
		Artigiano a = new Artigiano();
		a.setId(id);
		a.setNome(rs.getString("Nome"));
		a.setCognome(rs.getString("Cognome"));
		a.setPIva(rs.getString("PIva"));
		a.setEmail(rs.getString("Email"));
		a.setNote(rs.getString("Note"));
		a.setNazione(rs.getString("Nazione"));
		a.setRegione(rs.getString("Regione"));
		a.setCitta(rs.getString("Citta"));
		a.setCap(rs.getString("CAP"));
		a.setProvincia(rs.getString("Provincia"));
		a.setVia(rs.getString("Via"));
		a.setNCivico(rs.getString("NCivico"));
		a.setPathImg(rs.getString("PathImg"));
		
		if(deleted)
			a.setDataCancellazione(rs.getDate("DataCancellazione"));
		
		int idPartner = rs.getInt("TipoPartner");
		int idTipoArtigiano = rs.getInt("TipoArtigiano");
		
		rs.close();
		rs = st.executeQuery("SELECT * FROM Partner WHERE ID = " + idPartner);
		rs.next();
		Partner p = new Partner();
		p.setID(idPartner);
		p.setTipo(rs.getString("Tipo"));
		rs.close();
		
		rs = st.executeQuery("SELECT * FROM TipiArtigiani WHERE ID = " + idTipoArtigiano);
		rs.next();
		TipoArtigiano ta = new TipoArtigiano();
		ta.setId(idTipoArtigiano);
		ta.setTipo(rs.getString("Tipo"));
		rs.close();
		
		a.setPartner(p);
		a.setTipoArtigiano(ta);
		
		a.setTelefono(getTelefono(a, deleted));
		a.setFax(getFax(a, deleted));
		
		return a;
		
	}
	
	
	
	public Artigiano[] getListaArtigiani() throws SQLException {
		return getListaArtigianiCommon(false);
	}
	
	
	public Artigiano[] getListaArtigianiDeleted() throws SQLException {
		return getListaArtigianiCommon(true);
	}
	
	
	private Artigiano[] getListaArtigianiCommon(boolean deleted) throws SQLException {
		
		String tabella = "artigiani";
		if(deleted)
			tabella = "artigiani_deleted";
		

		Statement st = con.createStatement();
		
		ResultSet n = st.executeQuery("SELECT COUNT(*) FROM " + tabella);
		n.next();
		Artigiano[] a = new Artigiano[n.getInt(1)];
		n.close();
		
		ResultSet rs = st.executeQuery("SELECT * FROM " + tabella);
		
		int i = 0;
		while(rs.next()) {
			
			Artigiano ar = new Artigiano();
			ar.setId(rs.getInt("ID"));
			ar.setNome(rs.getString("Nome"));
			ar.setCognome(rs.getString("Cognome"));
			ar.setPIva(rs.getString("PIva"));
			ar.setEmail(rs.getString("Email"));
			ar.setNote(rs.getString("Note"));
			ar.setNazione(rs.getString("Nazione"));
			ar.setRegione(rs.getString("Regione"));
			ar.setCitta(rs.getString("Citta"));
			ar.setCap(rs.getString("CAP"));
			ar.setProvincia(rs.getString("Provincia"));
			ar.setVia(rs.getString("Via"));
			ar.setNCivico(rs.getString("NCivico"));
			ar.setPathImg(rs.getString("PathImg"));
			
			if(deleted)
				ar.setDataCancellazione(rs.getDate("DataCancellazione"));
			
			int idPartner = rs.getInt("TipoPartner");
			int idTipoArtigiano = rs.getInt("TipoArtigiano");
			
			ResultSet tmp;
			Statement st2 = con.createStatement();
			tmp = st2.executeQuery("SELECT * FROM Partner WHERE ID = " + idPartner);
			tmp.next();
			Partner p = new Partner();
			p.setID(idPartner);
			p.setTipo(tmp.getString("Tipo"));
			tmp.close();
			
			tmp = st2.executeQuery("SELECT * FROM TipiArtigiani WHERE ID = " + idTipoArtigiano);
			tmp.next();
			TipoArtigiano ta = new TipoArtigiano();
			ta.setId(idTipoArtigiano);
			ta.setTipo(tmp.getString("Tipo"));
			tmp.close();
			
			ar.setPartner(p);
			ar.setTipoArtigiano(ta);
			
			ar.setTelefono(getTelefono(ar, deleted));
			ar.setFax(getFax(ar, deleted));
			
			a[i] = ar;
			
			i++;
			
		}
		
		rs.close();
		st.close();
		
		return a;
		
	}
	
	

	public void modificaArtigiano(Artigiano a) throws SQLException {
	
		Statement st = con.createStatement();
		
		String query = "UPDATE artigiani SET "
			+ "Nome = '" + a.getNome() + "', Cognome = '" + a.getCognome() + "', PIva = '" + a.getPIva() + "', "
			+ "Email = '" + a.getEmail() + "', Note = '" + a.getNote() + "', Nazione = '" + a.getNazione() + "', "
			+ "Regione = '" + a.getRegione() + "', Citta = '" + a.getCitta() + "', CAP = '" + a.getCap() + "', "
			+ "Provincia = '" + a.getProvincia() + "', Via = '" + a.getVia() + "', NCivico = '" + a.getNCivico() + "', "
			+ "PathImg = '" + a.getPathImg() + "', TipoPartner = " + a.getPartner().getID() + ", TipoArtigiano = " + a.getTipoArtigiano().getId()
			+ " WHERE ID = " + a.getId();
		
		st.executeUpdate(query);
		
		settaTelFax(a, false);
	}

}
